////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxhal3.cpp
/// @brief Landing methods for CamX implementation of HAL3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// NOWHINE FILE NC010: Google Types
// NOWHINE FILE GR017: Google types
// NOWHINE FILE NC011: Google calls it 'init'

#include <system/camera_metadata.h>

#include "camera_metadata_hidden.h"

#include "chi.h"
#include "camxentry.h"
#include "camxhal3.h"
#include "camxhal3defaultrequest.h"
#include "camxhal3module.h"
#include "camxhaldevice.h"
#include "camxincs.h"
#include "camxvendortags.h"

CAMX_NAMESPACE_BEGIN

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// GetHALDevice
///
/// @brief  Extract the HAL device pointer from the camera3_device_t.
///         Precondition: pCamera3DeviceAPI has been checked for NULL
///
/// @param  pCamera3DeviceAPI The camera3_device_t pointer passed in from the application framework. Assumed that it has been
///                           checked against NULL.
///
/// @return A pointer to the HALSession object held in the opaque point in camera3_device_t.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if 0
typedef struct camera3_device {
    /**
     * common:
     *
     * Set to sizeof(camera3_device_t)
     */
    size_t common;

    /**
     * priv:
     *
     * Private data used by the HAL implementation.
     * Do not modify the contents of this struct directly.
     */
    void *priv;

    /**
     * ops:
     *
     * Function pointers used to call into the camera HAL implementation.
     * Each function must be non-NULL.
     */
    const struct camera3_device_ops *ops;

    /**
     * reserved:
     *
     * Reserved for future use; must be NULL.
     */
    void *reserved[6];
} camera3_device_t;
#endif
// 返回pCamera3DeviceAPI的private指针
static CAMX_INLINE HALDevice *GetHALDevice(
    const camera3_device_t *pCamera3DeviceAPI)
{
    CAMX_ASSERT(NULL != pCamera3DeviceAPI);

    return reinterpret_cast<HALDevice *>(pCamera3DeviceAPI->priv);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FormatToString
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const char *FormatToString(
    int format)
{
    const char *pFormatStr;

    switch (format)
    {
    case HAL_PIXEL_FORMAT_RGBA_8888:
        pFormatStr = "HAL_PIXEL_FORMAT_RGBA_8888";
        break;
    case HAL_PIXEL_FORMAT_RGBX_8888:
        pFormatStr = "HAL_PIXEL_FORMAT_RGBX_8888";
        break;
    case HAL_PIXEL_FORMAT_RGB_888:
        pFormatStr = "HAL_PIXEL_FORMAT_RGB_888";
        break;
    case HAL_PIXEL_FORMAT_RGB_565:
        pFormatStr = "HAL_PIXEL_FORMAT_RGB_565";
        break;
    case HAL_PIXEL_FORMAT_BGRA_8888:
        pFormatStr = "HAL_PIXEL_FORMAT_BGRA_8888";
        break;
    case HAL_PIXEL_FORMAT_YV12:
        pFormatStr = "HAL_PIXEL_FORMAT_YV12";
        break;
    case HAL_PIXEL_FORMAT_Y8:
        pFormatStr = "HAL_PIXEL_FORMAT_Y8";
        break;
    case HAL_PIXEL_FORMAT_Y16:
        pFormatStr = "HAL_PIXEL_FORMAT_Y16";
        break;
    case HAL_PIXEL_FORMAT_RAW16:
        pFormatStr = "HAL_PIXEL_FORMAT_RAW16";
        break;
    case HAL_PIXEL_FORMAT_RAW10:
        pFormatStr = "HAL_PIXEL_FORMAT_RAW10";
        break;
    case HAL_PIXEL_FORMAT_RAW12:
        pFormatStr = "HAL_PIXEL_FORMAT_RAW12";
        break;
    case HAL_PIXEL_FORMAT_RAW_OPAQUE:
        pFormatStr = "HAL_PIXEL_FORMAT_RAW_OPAQUE";
        break;
    case HAL_PIXEL_FORMAT_BLOB:
        pFormatStr = "HAL_PIXEL_FORMAT_BLOB";
        break;
    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
        pFormatStr = "HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED";
        break;
    case HAL_PIXEL_FORMAT_YCbCr_420_888:
        pFormatStr = "HAL_PIXEL_FORMAT_YCbCr_420_888";
        break;
    case HAL_PIXEL_FORMAT_YCbCr_422_888:
        pFormatStr = "HAL_PIXEL_FORMAT_YCbCr_422_888";
        break;
    case HAL_PIXEL_FORMAT_YCbCr_444_888:
        pFormatStr = "HAL_PIXEL_FORMAT_YCbCr_444_888";
        break;
    case HAL_PIXEL_FORMAT_FLEX_RGB_888:
        pFormatStr = "HAL_PIXEL_FORMAT_FLEX_RGB_888";
        break;
    case HAL_PIXEL_FORMAT_FLEX_RGBA_8888:
        pFormatStr = "HAL_PIXEL_FORMAT_FLEX_RGBA_8888";
        break;
    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
        pFormatStr = "HAL_PIXEL_FORMAT_YCbCr_422_SP";
        break;
    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
        pFormatStr = "HAL_PIXEL_FORMAT_YCrCb_420_SP";
        break;
    case HAL_PIXEL_FORMAT_YCbCr_422_I:
        pFormatStr = "HAL_PIXEL_FORMAT_YCbCr_422_I";
        break;
    default:
        pFormatStr = "Unknown Format";
        break;
    }

    return pFormatStr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// StreamTypeToString
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const char *StreamTypeToString(
    int streamType)
{
    const char *pStreamTypeStr;

    switch (streamType)
    {
    case CAMERA3_STREAM_OUTPUT:
        pStreamTypeStr = "CAMERA3_STREAM_OUTPUT";
        break;
    case CAMERA3_STREAM_INPUT:
        pStreamTypeStr = "CAMERA3_STREAM_INPUT";
        break;
    case CAMERA3_STREAM_BIDIRECTIONAL:
        pStreamTypeStr = "CAMERA3_STREAM_BIDIRECTIONAL";
        break;
    default:
        pStreamTypeStr = "Unknown Stream Type";
        break;
    }

    return pStreamTypeStr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DataSpaceToString
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const char *DataSpaceToString(
    android_dataspace_t dataSpace)
{
    const char *pDataSpaceStr;

    switch (dataSpace)
    {
    case HAL_DATASPACE_ARBITRARY:
        pDataSpaceStr = "HAL_DATASPACE_ARBITRARY";
        break;
    case HAL_DATASPACE_STANDARD_BT709:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT709";
        break;
    case HAL_DATASPACE_STANDARD_BT601_625:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT601_625";
        break;
    case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED";
        break;
    case HAL_DATASPACE_STANDARD_BT601_525:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT601_525";
        break;
    case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED";
        break;
    case HAL_DATASPACE_STANDARD_BT2020:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT2020";
        break;
    case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE";
        break;
    case HAL_DATASPACE_STANDARD_BT470M:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_BT470M";
        break;
    case HAL_DATASPACE_STANDARD_FILM:
        pDataSpaceStr = "HAL_DATASPACE_STANDARD_FILM";
        break;
    case HAL_DATASPACE_TRANSFER_LINEAR:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_LINEAR";
        break;
    case HAL_DATASPACE_TRANSFER_SRGB:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_SRGB";
        break;
    case HAL_DATASPACE_TRANSFER_SMPTE_170M:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_SMPTE_170M";
        break;
    case HAL_DATASPACE_TRANSFER_GAMMA2_2:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_GAMMA2_2";
        break;
    case HAL_DATASPACE_TRANSFER_GAMMA2_8:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_GAMMA2_8";
        break;
    case HAL_DATASPACE_TRANSFER_ST2084:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_ST2084";
        break;
    case HAL_DATASPACE_TRANSFER_HLG:
        pDataSpaceStr = "HAL_DATASPACE_TRANSFER_HLG";
        break;
    case HAL_DATASPACE_RANGE_FULL:
        pDataSpaceStr = "HAL_DATASPACE_RANGE_FULL";
        break;
    case HAL_DATASPACE_RANGE_LIMITED:
        pDataSpaceStr = "HAL_DATASPACE_RANGE_LIMITED";
        break;
    case HAL_DATASPACE_SRGB_LINEAR:
        pDataSpaceStr = "HAL_DATASPACE_SRGB_LINEAR";
        break;
    case HAL_DATASPACE_V0_SRGB_LINEAR:
        pDataSpaceStr = "HAL_DATASPACE_V0_SRGB_LINEAR";
        break;
    case HAL_DATASPACE_SRGB:
        pDataSpaceStr = "HAL_DATASPACE_SRGB";
        break;
    case HAL_DATASPACE_V0_SRGB:
        pDataSpaceStr = "HAL_DATASPACE_V0_SRGB";
        break;
    case HAL_DATASPACE_JFIF:
        pDataSpaceStr = "HAL_DATASPACE_JFIF";
        break;
    case HAL_DATASPACE_V0_JFIF:
        pDataSpaceStr = "HAL_DATASPACE_V0_JFIF";
        break;
    case HAL_DATASPACE_BT601_625:
        pDataSpaceStr = "HAL_DATASPACE_BT601_625";
        break;
    case HAL_DATASPACE_V0_BT601_625:
        pDataSpaceStr = "HAL_DATASPACE_V0_BT601_625";
        break;
    case HAL_DATASPACE_BT601_525:
        pDataSpaceStr = "HAL_DATASPACE_BT601_525";
        break;
    case HAL_DATASPACE_V0_BT601_525:
        pDataSpaceStr = "HAL_DATASPACE_V0_BT601_525";
        break;
    case HAL_DATASPACE_BT709:
        pDataSpaceStr = "HAL_DATASPACE_BT709";
        break;
    case HAL_DATASPACE_V0_BT709:
        pDataSpaceStr = "HAL_DATASPACE_V0_BT709";
        break;
    case HAL_DATASPACE_DEPTH:
        pDataSpaceStr = "HAL_DATASPACE_DEPTH";
        break;
    case HAL_DATASPACE_UNKNOWN:
        // case HAL_DATASPACE_STANDARD_UNSPECIFIED:
        // case HAL_DATASPACE_RANGE_UNSPECIFIED:
        // case HAL_DATASPACE_TRANSFER_UNSPECIFIED:
        // case HAL_DATASPACE_STANDARD_UNSPECIFIED:
    default:
        pDataSpaceStr = "HAL_DATASPACE_UNKNOWN";
        break;
    }

    return pDataSpaceStr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// RotationToString
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const char *RotationToString(
    int rotation)
{
    const char *pRotationStr;

    switch (rotation)
    {
    case CAMERA3_STREAM_ROTATION_0:
        pRotationStr = "CAMERA3_STREAM_ROTATION_0";
        break;
    case CAMERA3_STREAM_ROTATION_90:
        pRotationStr = "CAMERA3_STREAM_ROTATION_90";
        break;
    case CAMERA3_STREAM_ROTATION_180:
        pRotationStr = "CAMERA3_STREAM_ROTATION_180";
        break;
    case CAMERA3_STREAM_ROTATION_270:
        pRotationStr = "CAMERA3_STREAM_ROTATION_270";
        break;
    default:
        pRotationStr = "Unknown Rotation Angle";
        break;
    }
    return pRotationStr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hw_module_methods_t entry points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// open
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int open(
    const struct hw_module_t *pHwModuleAPI,
    const char *pCameraIdAPI,
    struct hw_device_t **ppHwDeviceAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Open);

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pHwModuleAPI);
    CAMX_ASSERT(NULL != pHwModuleAPI->id);
    CAMX_ASSERT(NULL != pHwModuleAPI->name);
    CAMX_ASSERT(NULL != pHwModuleAPI->author);
    CAMX_ASSERT(NULL != pHwModuleAPI->methods);
    CAMX_ASSERT('\0' != pCameraIdAPI[0]);
    CAMX_ASSERT(NULL != pCameraIdAPI);
    CAMX_ASSERT(NULL != ppHwDeviceAPI);

    if ((NULL != pHwModuleAPI) &&
        (NULL != pHwModuleAPI->id) &&
        (NULL != pHwModuleAPI->name) &&
        (NULL != pHwModuleAPI->author) &&
        (NULL != pHwModuleAPI->methods) &&
        (NULL != pCameraIdAPI) &&
        ('\0' != pCameraIdAPI[0]) &&
        (NULL != ppHwDeviceAPI))
    {
        UINT32 cameraId = 0;
        UINT32 logicalCameraId = 0;
        CHAR *pNameEnd = NULL;

        cameraId = OsUtils::StrToUL(pCameraIdAPI, &pNameEnd, 10);
        if (*pNameEnd != '\0')
        {
            CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid camera id: %s", pCameraIdAPI);
            // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
            result = CamxResultEInvalidArg;
        }

        if (CamxResultSuccess == result)
        {
            // Framework camera ID should only be known to these static landing functions, and the remap function
            logicalCameraId = HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIRemapCameraId(cameraId, IdRemapCamera);

            // Reserve the Torch resource for camera.
            // If torch already switched on, then turn it off and reserve for camera.
            HAL3Module::GetInstance()->ReserveTorchForCamera(
                HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIRemapCameraId(cameraId, IdRemapTorch), cameraId);

            // Sample code to show how the VOID* can be used in ExtendOpen
            ChiOverrideExtendOpen extend = {0};
            ChiOverrideToken tokenList[NumExtendSettings] = {{0}};
            extend.pTokens = tokenList;

            GenerateExtendOpenData(NumExtendSettings, &extend);

            // TODO
            // Reserve the camera to detect if it is already open or too many concurrent are open
            result = HAL3Module::GetInstance()->ProcessCameraOpen(logicalCameraId, &extend);
        }

        if (CamxResultSuccess == result)
        {
            // Sample code to show how the VOID* can be used in ModifySettings
            ChiOverrideModifySetting setting[NumExtendSettings] = {{{0}}};
            GenerateModifySettingsData(setting);

            for (UINT i = 0; i < NumExtendSettings; i++)
            {
                HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIModifySettings(&setting[i]);
            }

            const StaticSettings *pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();

            // Reserving 0xFFFF for setting that isnt copied across the extendopen and extendclose interface as well
            ChiOverrideModifySetting logLevels = {};

            logLevels.token.id = 0xFFFF;
            logLevels.token.size = sizeof(pStaticSettings->overrideLogLevels);
            // NOWHINE CP036a: Sample code needs access across typeless interface
            logLevels.pData = const_cast<UINT *>(&(pStaticSettings->overrideLogLevels));

            HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIModifySettings(&logLevels);

            CAMX_LOG_INFO(CamxLogGroupHAL, "Open: overrideCameraClose is %d , overrideCameraOpen is %d ",
                          pStaticSettings->overrideCameraClose, pStaticSettings->overrideCameraOpen);

            const HwModule *pHwModule = reinterpret_cast<const HwModule *>(pHwModuleAPI);
            HALDevice *pHALDevice = HALDevice::Create(pHwModule, logicalCameraId, cameraId);

            if (NULL != pHALDevice)
            {
                camera3_device_t *pCamera3Device = reinterpret_cast<camera3_device_t *>(pHALDevice->GetCameraDevice());
                *ppHwDeviceAPI = &pCamera3Device->common;
            }
            else
            {
                // HAL interface requires -ENODEV (EFailed) for all other internal errors
                result = CamxResultEFailed;
            }
        }

        if (CamxResultSuccess != result)
        {
            // If open fails, then release the Torch resource that we reserved.
            HAL3Module::GetInstance()->ReleaseTorchForCamera(
                HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIRemapCameraId(cameraId, IdRemapTorch), cameraId);
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument(s) for open()");
        // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
        result = CamxResultEInvalidArg;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// vendor_tag_ops_t entry points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_tag_count
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int get_tag_count(
    const vendor_tag_ops_t *pVendorTagOpsAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetTagCount);

    // Per Google, this parameter is extraneous
    CAMX_UNREFERENCED_PARAM(pVendorTagOpsAPI);

    return static_cast<int>(VendorTagManager::GetTagCount(TagSectionVisibility::TagSectionVisibleToFramework));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_all_tags
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void get_all_tags(
    const vendor_tag_ops_t *pVendorTagOpsAPI,
    uint32_t *pTagArrayAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetAllTags);

    // Per Google, this parameter is extraneous
    CAMX_UNREFERENCED_PARAM(pVendorTagOpsAPI);

    CAMX_STATIC_ASSERT(sizeof(pTagArrayAPI[0]) == sizeof(VendorTag));

    CAMX_ASSERT(NULL != pTagArrayAPI);
    if (NULL != pTagArrayAPI)
    {
        VendorTag *pVendorTags = static_cast<VendorTag *>(pTagArrayAPI);
        VendorTagManager::GetAllTags(pVendorTags, TagSectionVisibility::TagSectionVisibleToFramework);
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 2 for get_all_tags()");
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_section_name
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const char *get_section_name(
    const vendor_tag_ops_t *pVendorTagOpsAPI,
    uint32_t tagAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetSectionName);

    // Per Google, this parameter is extraneous
    CAMX_UNREFERENCED_PARAM(pVendorTagOpsAPI);

    CAMX_STATIC_ASSERT(sizeof(tagAPI) == sizeof(VendorTag));

    return VendorTagManager::GetSectionName(static_cast<VendorTag>(tagAPI));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_tag_name
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const char *get_tag_name(
    const vendor_tag_ops_t *pVendorTagOpsAPI,
    uint32_t tagAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetTagName);

    // Per Google, this parameter is extraneous
    CAMX_UNREFERENCED_PARAM(pVendorTagOpsAPI);

    CAMX_STATIC_ASSERT(sizeof(tagAPI) == sizeof(VendorTag));

    return VendorTagManager::GetTagName(static_cast<VendorTag>(tagAPI));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_tag_type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int get_tag_type(
    const vendor_tag_ops_t *pVendorTagOpsAPI,
    uint32_t tagAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetTagType);

    // Per Google, this parameter is extraneous
    CAMX_UNREFERENCED_PARAM(pVendorTagOpsAPI);

    CAMX_STATIC_ASSERT(sizeof(tagAPI) == sizeof(VendorTag));

    VendorTagType vendorTagType = VendorTagManager::GetTagType(static_cast<VendorTag>(tagAPI));
    return static_cast<int>(vendorTagType);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// camera_module_t entry points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_number_of_cameras
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int get_number_of_cameras(void)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetNumberOfCameras);

    return static_cast<int>(HAL3Module::GetInstance()->GetNumCameras());
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_camera_info
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int get_camera_info(
    int cameraIdAPI,
    struct camera_info *pInfoAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetCameraInfo);

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pInfoAPI);

    if (NULL != pInfoAPI)
    {
        UINT32 cameraId = static_cast<UINT32>(cameraIdAPI);
        UINT32 logicalCameraId =
            HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIRemapCameraId(cameraId,
                                                                              IdRemapCamera);

        CameraInfo *pInfo = reinterpret_cast<CameraInfo *>(pInfoAPI);
        result = HAL3Module::GetInstance()->GetCameraInfo(logicalCameraId, pInfo);
        if (CamxResultSuccess != result)
        {
            CAMX_LOG_ERROR(CamxLogGroupHAL, "HAL3Module::GetCameraInfo() failed with result %s", CamxResultStrings[result]);
            // HAL interface requires -ENODEV (EFailed) for all other failures
            result = CamxResultEFailed;
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 2 for get_camera_info()");
        // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
        result = CamxResultEInvalidArg;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set_callbacks
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int set_callbacks(
    const camera_module_callbacks_t *pModuleCbsAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3SetCallbacks);

    CamxResult result = CamxResultSuccess;

    const CameraModuleCbs *pCameraModuleCbs = reinterpret_cast<const CameraModuleCbs *>(pModuleCbsAPI);
    result = HAL3Module::GetInstance()->SetCbs(pCameraModuleCbs);
    if (CamxResultSuccess != result)
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "HAL3Module::SetCbs() failed with result %s", CamxResultStrings[result]);
        // HAL interface requires -ENODEV (EFailed) for all other failures
        result = CamxResultEFailed;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// get_vendor_tag_ops
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void get_vendor_tag_ops(
    vendor_tag_ops_t *pVendorTagOpsAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3GetVendorTagOps);

    CAMX_ASSERT(NULL != pVendorTagOpsAPI);

    if (NULL != pVendorTagOpsAPI)
    {
        pVendorTagOpsAPI->get_tag_count = get_tag_count;
        pVendorTagOpsAPI->get_all_tags = get_all_tags;
        pVendorTagOpsAPI->get_section_name = get_section_name;
        pVendorTagOpsAPI->get_tag_name = get_tag_name;
        pVendorTagOpsAPI->get_tag_type = get_tag_type;
        pVendorTagOpsAPI->reserved[0] = NULL;
    }

    /// @todo (CAMX-1223) Remove below and set the vendor tag ops in hal3test
    // This is the workaround for presil HAL3test on Windows
    // On Device, set_camera_metadata_vendor_ops will be call the set the
    // static vendor tag operation in camera_metadata.c
    //
    // On Windows side, theoretically hal3test should mimic what Android framework
    // does and call the set_camera_metadata_vendor_ops function in libcamxext library
    // However, in Windows, if both hal3test.exe and hal.dll link to libcamxext library,
    // there are two different instance of static varibles sit in different memory location.
    // Even if set_camera_metadata_vendor_ops is called in hal3test, when hal try to
    // access to vendor tag ops, it is still not set.
    set_camera_metadata_vendor_ops(pVendorTagOpsAPI);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// open_legacy
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int open_legacy(
    const struct hw_module_t *pHwModuleAPI,
    const char *pCameraIdAPI,
    uint32_t halVersion,
    struct hw_device_t **ppHwDeviceAPI)
{
    CAMX_UNREFERENCED_PARAM(pHwModuleAPI);
    CAMX_UNREFERENCED_PARAM(pCameraIdAPI);
    CAMX_UNREFERENCED_PARAM(halVersion);
    CAMX_UNREFERENCED_PARAM(ppHwDeviceAPI);

    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3OpenLegacy);

    /// Intentionally do nothing. HAL interface requires -ENOSYS (ENotImplemented) result code.

    return Utils::CamxResultToErrno(CamxResultENotImplemented);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// set_torch_mode
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int set_torch_mode(
    const char *pCameraIdAPI,
    bool enabledAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3SetTorchMode);

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pCameraIdAPI);
    CAMX_ASSERT('\0' != pCameraIdAPI[0]);

    if ((NULL != pCameraIdAPI) &&
        ('\0' != pCameraIdAPI[0]))
    {
        UINT32 cameraId = 0;
        CHAR *pNameEnd = NULL;
        cameraId = OsUtils::StrToUL(pCameraIdAPI, &pNameEnd, 10);

        if (*pNameEnd != '\0')
        {
            CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid camera id: %s", pCameraIdAPI);
            // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
            result = CamxResultEInvalidArg;
        }

        if (CamxResultSuccess == result)
        {
            UINT32 logicalCameraId =
                HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIRemapCameraId(cameraId, IdRemapTorch);
            BOOL enableTorch = (true == enabledAPI) ? TRUE : FALSE;

            result = HAL3Module::GetInstance()->SetTorchMode(logicalCameraId, cameraId, enableTorch);
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 1 for set_torch_mode()");
        // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
        result = CamxResultEInvalidArg;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int init()
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Init);

    /// Intentionally do nothing for now. Left as a placeholder for future use.
    /// @todo (CAMX-264) - Determine what, if any, CSL initialization should be done after module load

    return Utils::CamxResultToErrno(CamxResultSuccess);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hw_device_t entry points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// close
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int close(
    struct hw_device_t *pHwDeviceAPI)
{
    CamxResult result = CamxResultSuccess;
    {
        CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Close);

        CAMX_ASSERT(NULL != pHwDeviceAPI);

        CAMX_LOG_INFO(CamxLogGroupHAL, "close(): %p", pHwDeviceAPI);

        if (NULL != pHwDeviceAPI)
        {
            Camera3Device *pCamera3Device = reinterpret_cast<Camera3Device *>(pHwDeviceAPI);
            HALDevice *pHALDevice = static_cast<HALDevice *>(pCamera3Device->pPrivateData);

            CAMX_ASSERT(NULL != pHALDevice);

            if (NULL != pHALDevice)
            {
                // Sample code to show how the VOID* can be used in ExtendOpen
                ChiOverrideExtendClose extend = {0};
                ChiOverrideToken tokenList[NumExtendSettings] = {{0}};
                extend.pTokens = tokenList;

                GenerateExtendCloseData(NumExtendSettings, &extend);

                // Allow the camera to be reopened
                HAL3Module::GetInstance()->ProcessCameraClose(pHALDevice->GetCameraId(), &extend);

                // Sample code to show how the VOID* can be used in ModifySettings
                ChiOverrideModifySetting setting[NumExtendSettings] = {{{0}}};
                GenerateModifySettingsData(setting);

                for (UINT i = 0; i < NumExtendSettings; i++)
                {
                    HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIModifySettings(&setting[i]);
                }
                const StaticSettings *pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();
                CAMX_LOG_INFO(CamxLogGroupHAL, "Close: overrideCameraClose is %d , overrideCameraOpen is %d ",
                              pStaticSettings->overrideCameraClose, pStaticSettings->overrideCameraOpen);

                result = pHALDevice->Close();

                CAMX_LOG_VERBOSE(CamxLogGroupHAL, "Close done on cameraId %d", pHALDevice->GetCameraId());
                pHALDevice->CloseCachedSensorHandles(pHALDevice->GetCameraId());

                // Unconditionally destroy the HALSession object
                pHALDevice->Destroy();
                pHALDevice = NULL;
            }
            else
            {
                CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 1 for close()");
                result = CamxResultEInvalidArg;
            }
        }
        else
        {
            CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 1 for close()");
            result = CamxResultEInvalidArg;
        }
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// camera3_device_ops_t entry points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// initialize
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int initialize(
    const struct camera3_device *pCamera3DeviceAPI,
    const camera3_callback_ops_t *pCamera3CbOpsAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Initialize);

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pCamera3DeviceAPI);
    CAMX_ASSERT(NULL != pCamera3DeviceAPI->priv);

    CAMX_LOG_INFO(CamxLogGroupHAL, "initialize(): %p, %p", pCamera3DeviceAPI, pCamera3CbOpsAPI);

    if ((NULL != pCamera3DeviceAPI) &&
        (NULL != pCamera3DeviceAPI->priv))
    {
        HALDevice *pHALDevice = GetHALDevice(pCamera3DeviceAPI);
        const Camera3CbOps *pCamera3CbOps = reinterpret_cast<const Camera3CbOps *>(pCamera3CbOpsAPI);

        pHALDevice->SetCallbackOps(pCamera3CbOps);
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument(s) for initialize()");
        // HAL interface requires -ENODEV (EFailed) if initialization fails for any reason, including invalid arguments.
        result = CamxResultEFailed;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// configure_streams
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int configure_streams(
    const struct camera3_device *pCamera3DeviceAPI,
    camera3_stream_configuration_t *pStreamConfigsAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3ConfigureStreams);

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pCamera3DeviceAPI);
    CAMX_ASSERT(NULL != pCamera3DeviceAPI->priv);
    CAMX_ASSERT(NULL != pStreamConfigsAPI);
    CAMX_ASSERT(pStreamConfigsAPI->num_streams > 0);
    CAMX_ASSERT(NULL != pStreamConfigsAPI->streams);

    if ((NULL != pCamera3DeviceAPI) &&
        (NULL != pCamera3DeviceAPI->priv) &&
        (NULL != pStreamConfigsAPI) &&
        (pStreamConfigsAPI->num_streams > 0) &&
        (NULL != pStreamConfigsAPI->streams))
    {
        CAMX_LOG_INFO(CamxLogGroupHAL, "Number of streams: %d", pStreamConfigsAPI->num_streams);
        
        // 遍历流配置中的所有流并打印
        for (UINT32 stream = 0; stream < pStreamConfigsAPI->num_streams; stream++)
        {
            CAMX_ASSERT(NULL != pStreamConfigsAPI->streams[stream]);

            if (NULL == pStreamConfigsAPI->streams[stream])
            {
                CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 2 for configure_streams()");
                // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
                result = CamxResultEInvalidArg;
                break;
            }
            else
            {
                CAMX_LOG_INFO(CamxLogGroupHAL, "  stream[%d] = %p - info:", stream,
                              pStreamConfigsAPI->streams[stream]);
                CAMX_LOG_INFO(CamxLogGroupHAL, "            format       : %d, %s",
                              pStreamConfigsAPI->streams[stream]->format,
                              FormatToString(pStreamConfigsAPI->streams[stream]->format));
                CAMX_LOG_INFO(CamxLogGroupHAL, "            width        : %d",
                              pStreamConfigsAPI->streams[stream]->width);
                CAMX_LOG_INFO(CamxLogGroupHAL, "            height       : %d",
                              pStreamConfigsAPI->streams[stream]->height);
                CAMX_LOG_INFO(CamxLogGroupHAL, "            stream_type  : %08x, %s",
                              pStreamConfigsAPI->streams[stream]->stream_type,
                              StreamTypeToString(pStreamConfigsAPI->streams[stream]->stream_type));
                CAMX_LOG_INFO(CamxLogGroupHAL, "            usage        : %08x",
                              pStreamConfigsAPI->streams[stream]->usage);
                CAMX_LOG_INFO(CamxLogGroupHAL, "            max_buffers  : %d",
                              pStreamConfigsAPI->streams[stream]->max_buffers);
                CAMX_LOG_INFO(CamxLogGroupHAL, "            rotation     : %08x, %s",
                              pStreamConfigsAPI->streams[stream]->rotation,
                              RotationToString(pStreamConfigsAPI->streams[stream]->rotation));
                CAMX_LOG_INFO(CamxLogGroupHAL, "            data_space   : %08x, %s",
                              pStreamConfigsAPI->streams[stream]->data_space,
                              DataSpaceToString(pStreamConfigsAPI->streams[stream]->data_space));
                CAMX_LOG_INFO(CamxLogGroupHAL, "            priv         : %p",
                              pStreamConfigsAPI->streams[stream]->priv);
            }
        }
        CAMX_LOG_INFO(CamxLogGroupHAL, "  operation_mode: %d", pStreamConfigsAPI->operation_mode);
        
        // 通过pCamera3DeviceAPI获取private指针，即HALDevice类型的指针
        HALDevice *pHALDevice = GetHALDevice(pCamera3DeviceAPI);
        // 将接口强转为实现类
        Camera3StreamConfig *pStreamConfigs = reinterpret_cast<Camera3StreamConfig *>(pStreamConfigsAPI);

        // 调用pHALDevice中的配流函数指针
        result = pHALDevice->ConfigureStreams(pStreamConfigs);

        if ((CamxResultSuccess != result) && (CamxResultEInvalidArg != result))
        {
            // HAL interface requires -ENODEV (EFailed) if a fatal error occurs
            result = CamxResultEFailed;
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument(s) for configure_streams()");
        // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
        result = CamxResultEInvalidArg;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// construct_default_request_settings
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const camera_metadata_t *construct_default_request_settings(
    const struct camera3_device *pCamera3DeviceAPI,
    int requestTemplateAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3ConstructDefaultRequestSettings);

    const Metadata *pMetadata = NULL;

    CAMX_ASSERT(NULL != pCamera3DeviceAPI);
    CAMX_ASSERT(NULL != pCamera3DeviceAPI->priv);

    if ((NULL != pCamera3DeviceAPI) && (NULL != pCamera3DeviceAPI->priv))
    {
        HALDevice *pHALDevice = GetHALDevice(pCamera3DeviceAPI);
        Camera3RequestTemplate requestTemplate = static_cast<Camera3RequestTemplate>(requestTemplateAPI);
        const Metadata *pOverrideMetadata = NULL;

        HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIGetDefaultRequestSettings(pHALDevice->GetCameraId(),
                                                                                      requestTemplate,
                                                                                      &pOverrideMetadata);

        UINT32 logicalCameraId =
            HAL3Module::GetInstance()->GetCHIAppCallbacks()->CHIRemapCameraId(pHALDevice->GetFwCameraId(),
                                                                              IdRemapTorch);

        pMetadata = HAL3DefaultRequest::ConstructDefaultRequestSettings(logicalCameraId, requestTemplate);

        if ((NULL != pMetadata) && (NULL != pOverrideMetadata))
        {
            CamxResult result = CamxResultSuccess;

            // NOWHINE CP036a: Since google function is non-const, had to add the const_cast
            result = HAL3MetadataUtil::MergeMetadata(const_cast<Metadata *>(pMetadata), pOverrideMetadata);

            if (CamxResultSuccess == result)
            {
                CAMX_LOG_INFO(CamxLogGroupHAL, "Override specific tags added to construct default settings");
            }
            else
            {
                ///@ todo (CAMX-1797) Handle failure case - ideally will never happen
                CAMX_LOG_ERROR(CamxLogGroupHAL, "Could not add override specific tags to construct default settings");
            }
        }
        else
        {
            if (NULL == pMetadata)
            {
                CAMX_LOG_ERROR(CamxLogGroupHAL, "Construct default settings failures");
            }
            if (NULL == pOverrideMetadata)
            {
                CAMX_LOG_INFO(CamxLogGroupHAL, "No override specific tags given by override");
            }
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument(s) for initialize()");
    }

    return reinterpret_cast<const camera_metadata_t *>(pMetadata);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// process_capture_request
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int process_capture_request(
    const struct camera3_device *pCamera3DeviceAPI,
    camera3_capture_request_t *pCaptureRequestAPI)
{
    UINT64 frameworkFrameNum = 0;

    if (NULL != pCaptureRequestAPI)
    {
        frameworkFrameNum = pCaptureRequestAPI->frame_number;
    }

    CAMX_ENTRYEXIT_SCOPE_ID(CamxLogGroupHAL, SCOPEEventHAL3ProcessCaptureRequest, frameworkFrameNum);

    CAMX_TRACE_ASYNC_BEGIN_F(CamxLogGroupHAL, frameworkFrameNum, "HAL3: RequestTrace");

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pCamera3DeviceAPI);
    CAMX_ASSERT(NULL != pCamera3DeviceAPI->priv);
    CAMX_ASSERT(NULL != pCaptureRequestAPI);
    CAMX_ASSERT(pCaptureRequestAPI->num_output_buffers > 0);
    CAMX_ASSERT(NULL != pCaptureRequestAPI->output_buffers);

    if ((NULL != pCamera3DeviceAPI) &&
        (NULL != pCamera3DeviceAPI->priv) &&
        (NULL != pCaptureRequestAPI) &&
        (pCaptureRequestAPI->num_output_buffers > 0) &&
        (NULL != pCaptureRequestAPI->output_buffers))
    {
        /// @todo (CAMX-337): Go deeper into camera3_capture_request_t struct for validation

        // 取出priv指针
        HALDevice *pHALDevice = GetHALDevice(pCamera3DeviceAPI);
        Camera3CaptureRequest *pRequest = reinterpret_cast<Camera3CaptureRequest *>(pCaptureRequestAPI);

        CAMX_LOG_INFO(CamxLogGroupHAL, "frame_number %d", pCaptureRequestAPI->frame_number);
        CAMX_LOG_INFO(CamxLogGroupHAL, "num_output_buffers %d", pCaptureRequestAPI->num_output_buffers);
        CAMX_LOG_INFO(CamxLogGroupHAL, "output_buffers %p", pCaptureRequestAPI->output_buffers);
        if (NULL != pCaptureRequestAPI->output_buffers)
        {
            for (UINT i = 0; i < pCaptureRequestAPI->num_output_buffers; i++)
            {
                CAMX_LOG_INFO(CamxLogGroupHAL, "    output_buffers[%d] : %p - info", i, &pCaptureRequestAPI->output_buffers[i]);
                CAMX_LOG_INFO(CamxLogGroupHAL, "        buffer  : %p", pCaptureRequestAPI->output_buffers[i].buffer);
                CAMX_LOG_INFO(CamxLogGroupHAL, "        status  : %08x", pCaptureRequestAPI->output_buffers[i].status);
                CAMX_LOG_INFO(CamxLogGroupHAL, "        stream  : %p", pCaptureRequestAPI->output_buffers[i].stream);
                if (HAL_PIXEL_FORMAT_BLOB == pCaptureRequestAPI->output_buffers[i].stream->format)
                {
                    CAMX_TRACE_ASYNC_BEGIN_F(CamxLogGroupNone, pCaptureRequestAPI->frame_number, "SNAPSHOT frameID: %d",
                                             pCaptureRequestAPI->frame_number);
                    CAMX_TRACE_ASYNC_BEGIN_F(CamxLogGroupNone, pCaptureRequestAPI->frame_number, "SHUTTERLAG frameID: %d",
                                             pCaptureRequestAPI->frame_number);
                }
            }
        }
        CAMX_LOG_INFO(CamxLogGroupHAL, "input_buffer %p", pCaptureRequestAPI->input_buffer);
        if (NULL != pCaptureRequestAPI->input_buffer)
        {
            CAMX_LOG_INFO(CamxLogGroupHAL, "        buffer  : %p", pCaptureRequestAPI->input_buffer->buffer);
            CAMX_LOG_INFO(CamxLogGroupHAL, "        status  : %08x", pCaptureRequestAPI->input_buffer->status);
            CAMX_LOG_INFO(CamxLogGroupHAL, "        stream  : %p", pCaptureRequestAPI->input_buffer->stream);
        }
        CAMX_LOG_INFO(CamxLogGroupHAL, "settings %p", pCaptureRequestAPI->settings);

        result = pHALDevice->ProcessCaptureRequest(pRequest);

        if ((CamxResultSuccess != result) && (CamxResultEInvalidArg != result))
        {
            // HAL interface requires -ENODEV (EFailed) if a fatal error occurs
            result = CamxResultEFailed;
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument(s) for process_capture_request()");
        // HAL interface requires -EINVAL (EInvalidArg) for invalid arguments
        result = CamxResultEInvalidArg;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// dump
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void dump(
    const struct camera3_device *pCamera3DeviceAPI,
    int fdAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Dump);

    CAMX_LOG_TO_FILE(fdAPI, 0, "###############  Chi Snapshot  ###############");

    if ((NULL != pCamera3DeviceAPI) &&
        (NULL != pCamera3DeviceAPI->priv))
    {
        HAL3Module::GetInstance()->Dump(fdAPI);

        HALDevice *pHALDevice = GetHALDevice(pCamera3DeviceAPI);
        pHALDevice->Dump(fdAPI);

        ChiDumpState(fdAPI);
    }
    else
    {
        CAMX_LOG_TO_FILE(fdAPI, 2, "Invalid camera3_device pointer, cannot dump info");
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// flush
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int flush(
    const struct camera3_device *pCamera3DeviceAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3Flush);

    CamxResult result = CamxResultSuccess;

    CAMX_ASSERT(NULL != pCamera3DeviceAPI);
    CAMX_ASSERT(NULL != pCamera3DeviceAPI->priv);

    CAMX_LOG_INFO(CamxLogGroupHAL, "flush(): %p", pCamera3DeviceAPI);

    if ((NULL != pCamera3DeviceAPI) &&
        (NULL != pCamera3DeviceAPI->priv))
    {
        HALDevice *pHALDevice = GetHALDevice(pCamera3DeviceAPI);

        result = pHALDevice->Flush();

        if ((CamxResultSuccess != result) && (CamxResultEInvalidArg != result))
        {
            // HAL interface requires -ENODEV (EFailed) if flush fails
            result = CamxResultEFailed;
        }
    }
    else
    {
        CAMX_LOG_ERROR(CamxLogGroupHAL, "Invalid argument 1 for flush()");
        // HAL interface requires -EINVAL (EInvalidArg) if arguments are invalid
        result = CamxResultEInvalidArg;
    }

    return Utils::CamxResultToErrno(result);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// camera_module_callbacks_t exit points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// camera_device_status_change
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void camera_device_status_change(
    const struct camera_module_callbacks *pModuleCbsAPI,
    int cameraIdAPI,
    int newStatusAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3CameraDeviceStatusChange);

    pModuleCbsAPI->camera_device_status_change(pModuleCbsAPI, cameraIdAPI, newStatusAPI);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// torch_mode_status_change
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void torch_mode_status_change(
    const struct camera_module_callbacks *pModuleCbsAPI,
    const char *pCameraIdAPI,
    int newStatusAPI)
{
    CAMX_ENTRYEXIT_SCOPE(CamxLogGroupHAL, SCOPEEventHAL3TorchModeStatusChange);

    if (NULL != pModuleCbsAPI)
    {
        pModuleCbsAPI->torch_mode_status_change(pModuleCbsAPI, pCameraIdAPI, newStatusAPI);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// camera3_callback_ops_t exit points
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// process_capture_result
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void process_capture_result(
    const struct camera3_callback_ops *pCamera3CbOpsAPI,
    const camera3_capture_result_t *pCaptureResultAPI)
{
    UINT64 frameworkFrameNum = 0;

    if (NULL != pCaptureResultAPI)
    {
        frameworkFrameNum = pCaptureResultAPI->frame_number;

        CAMX_LOG_INFO(CamxLogGroupHAL, "frame_number %d", pCaptureResultAPI->frame_number);
        CAMX_LOG_INFO(CamxLogGroupHAL, "num_output_buffers %d", pCaptureResultAPI->num_output_buffers);
        CAMX_LOG_INFO(CamxLogGroupHAL, "output_buffers %p", pCaptureResultAPI->output_buffers);
        if (NULL != pCaptureResultAPI->output_buffers)
        {
            for (UINT i = 0; i < pCaptureResultAPI->num_output_buffers; i++)
            {
                CAMX_LOG_INFO(CamxLogGroupHAL, "    output_buffers[%d] : %p - info", i, &pCaptureResultAPI->output_buffers[i]);
                CAMX_LOG_INFO(CamxLogGroupHAL, "        buffer  : %p", pCaptureResultAPI->output_buffers[i].buffer);
                CAMX_LOG_INFO(CamxLogGroupHAL, "        status  : %08x", pCaptureResultAPI->output_buffers[i].status);
                CAMX_LOG_INFO(CamxLogGroupHAL, "        stream  : %p", pCaptureResultAPI->output_buffers[i].stream);

                if (HAL_PIXEL_FORMAT_BLOB == pCaptureResultAPI->output_buffers[i].stream->format)
                {
                    CAMX_TRACE_ASYNC_END_F(CamxLogGroupNone, pCaptureResultAPI->frame_number, "SNAPSHOT frameID: %d",
                                           pCaptureResultAPI->frame_number);
                }
            }
        }
        CAMX_LOG_INFO(CamxLogGroupHAL, "input_buffer %p", pCaptureResultAPI->input_buffer);
        if (NULL != pCaptureResultAPI->input_buffer)
        {
            CAMX_LOG_INFO(CamxLogGroupHAL, "        buffer  : %p", pCaptureResultAPI->input_buffer->buffer);
            CAMX_LOG_INFO(CamxLogGroupHAL, "        status  : %08x", pCaptureResultAPI->input_buffer->status);
            CAMX_LOG_INFO(CamxLogGroupHAL, "        stream  : %p", pCaptureResultAPI->input_buffer->stream);
        }
        CAMX_LOG_INFO(CamxLogGroupHAL, "partial_result %d", pCaptureResultAPI->partial_result);
        CAMX_LOG_INFO(CamxLogGroupHAL, "result %p", pCaptureResultAPI->result);
    }

    CAMX_ENTRYEXIT_SCOPE_ID(CamxLogGroupHAL, SCOPEEventHAL3ProcessCaptureResult, frameworkFrameNum);

    // 调去framework层
    pCamera3CbOpsAPI->process_capture_result(pCamera3CbOpsAPI, pCaptureResultAPI);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// notify
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void notify(
    const struct camera3_callback_ops *pCamera3CbOpsAPI,
    const camera3_notify_msg_t *pNotifyMessageAPI)
{
    if (NULL != pNotifyMessageAPI)
    {
        CAMX_TRACE_SYNC_BEGIN_F(CamxLogGroupHAL, "HAL3 Notify Type: %u", pNotifyMessageAPI->type);
    }

    BOOL bNeedNotify = TRUE;
    if (NULL != pNotifyMessageAPI)
    {
        CAMX_LOG_INFO(CamxLogGroupHAL, "type %08x", pNotifyMessageAPI->type);
        switch (pNotifyMessageAPI->type)
        {
        case CAMERA3_MSG_ERROR:
            CAMX_LOG_INFO(CamxLogGroupHAL, "    frame_number %d", pNotifyMessageAPI->message.error.frame_number);
            CAMX_LOG_INFO(CamxLogGroupHAL, "    error_code %08x", pNotifyMessageAPI->message.error.error_code);
            CAMX_LOG_INFO(CamxLogGroupHAL, "    error_stream %p", pNotifyMessageAPI->message.error.error_stream);
            break;
        case CAMERA3_MSG_SHUTTER:
            CAMX_LOG_INFO(CamxLogGroupHAL, "    frame_number %d", pNotifyMessageAPI->message.shutter.frame_number);
            CAMX_LOG_INFO(CamxLogGroupHAL, "    timestamp %llu", pNotifyMessageAPI->message.shutter.timestamp);
            CAMX_TRACE_ASYNC_END_F(CamxLogGroupNone, pNotifyMessageAPI->message.shutter.frame_number,
                                   "SHUTTERLAG frameID: %d", pNotifyMessageAPI->message.shutter.frame_number);
            break;
        default:
            bNeedNotify = FALSE;
            CAMX_LOG_INFO(CamxLogGroupHAL, "Unknown message type");
            break;
        }
    }

    if (TRUE == bNeedNotify)
    {
        pCamera3CbOpsAPI->notify(pCamera3CbOpsAPI, pNotifyMessageAPI);
    }

    CAMX_TRACE_SYNC_END(CamxLogGroupHAL);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Jump table for HAL3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
JumpTableHAL3 g_jumpTableHAL3 =
    {
        open,
        get_number_of_cameras,
        get_camera_info,
        set_callbacks,
        get_vendor_tag_ops,
        open_legacy,
        set_torch_mode,
        init,
        get_tag_count,
        get_all_tags,
        get_section_name,
        get_tag_name,
        get_tag_type,
        close,
        initialize,
        configure_streams,
        construct_default_request_settings,
        process_capture_request,
        dump,
        flush,
        camera_device_status_change,
        torch_mode_status_change,
        process_capture_result,
        notify};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GenerateExtendOpenData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void GenerateExtendOpenData(
    UINT32 numTokens,
    ChiOverrideExtendOpen *pExtend)
{
    const StaticSettings *pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();

    pExtend->numTokens = numTokens;

    pExtend->pTokens[0].id = 0;
    pExtend->pTokens[0].size = sizeof(pStaticSettings->overrideForceUsecaseId);
    pExtend->pTokens[1].id = 1;
    pExtend->pTokens[1].size = sizeof(pStaticSettings->overrideDisableZSL);
    pExtend->pTokens[2].id = 2;
    pExtend->pTokens[2].size = sizeof(pStaticSettings->overrideGPURotationUsecase);
    pExtend->pTokens[3].id = 3;
    pExtend->pTokens[3].size = sizeof(pStaticSettings->overrideEnableMFNR);
    pExtend->pTokens[4].id = 4;
    pExtend->pTokens[4].size = sizeof(pStaticSettings->anchorSelectionAlgoForMFNR);
    pExtend->pTokens[5].id = 5;
    pExtend->pTokens[5].size = sizeof(pStaticSettings->overrideHFRNo3AUseCase);
    pExtend->pTokens[6].id = 6;
    pExtend->pTokens[6].size = sizeof(pStaticSettings->overrideForceSensorMode);
    pExtend->pTokens[7].id = 7;
    pExtend->pTokens[7].size = sizeof(pStaticSettings->defaultMaxFPS);
    pExtend->pTokens[8].id = 8;
    pExtend->pTokens[8].size = sizeof(pStaticSettings->fovcEnable);
    pExtend->pTokens[9].id = 9;
    pExtend->pTokens[9].size = sizeof(pStaticSettings->overrideCameraClose);
    pExtend->pTokens[10].id = 10;
    pExtend->pTokens[10].size = sizeof(pStaticSettings->overrideCameraOpen);
    pExtend->pTokens[11].id = 11;
    pExtend->pTokens[11].size = sizeof(pStaticSettings->EISV2Enable);
    pExtend->pTokens[12].id = 12;
    pExtend->pTokens[12].size = sizeof(pStaticSettings->EISV3Enable);
    pExtend->pTokens[13].id = 13;
    pExtend->pTokens[13].size = sizeof(pStaticSettings->numPCRsBeforeStreamOn);
    pExtend->pTokens[14].id = 14;
    pExtend->pTokens[14].size = sizeof(pStaticSettings->statsProcessingSkipFactor);
    pExtend->pTokens[15].id = 15;
    pExtend->pTokens[15].size = sizeof(pStaticSettings->multiCameraSATEnable);
    pExtend->pTokens[16].id = 16;
    pExtend->pTokens[16].size = sizeof(pStaticSettings->dumpDebugDataEveryProcessResult);
    pExtend->pTokens[17].id = 17;
    pExtend->pTokens[17].size = sizeof(pStaticSettings->multiCameraVREnable);
    pExtend->pTokens[18].id = 18;
    pExtend->pTokens[18].size = sizeof(pStaticSettings->overrideGPUDownscaleUsecase);
    pExtend->pTokens[19].id = 19;
    pExtend->pTokens[19].size = sizeof(pStaticSettings->advanceFeatureMask);
    pExtend->pTokens[20].id = 20;
    pExtend->pTokens[20].size = sizeof(pStaticSettings->disableASDStatsProcessing);
    pExtend->pTokens[21].id = 21;
    pExtend->pTokens[21].size = sizeof(pStaticSettings->multiCameraFrameSync);
    pExtend->pTokens[22].id = 22;
    pExtend->pTokens[22].size = sizeof(pStaticSettings->outputFormat);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GenerateExtendCloseData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void GenerateExtendCloseData(
    UINT32 numTokens,
    ChiOverrideExtendClose *pExtend)
{
    const StaticSettings *pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();

    pExtend->numTokens = numTokens;

    pExtend->pTokens[0].id = 0;
    pExtend->pTokens[0].size = sizeof(pStaticSettings->overrideForceUsecaseId);
    pExtend->pTokens[1].id = 1;
    pExtend->pTokens[1].size = sizeof(pStaticSettings->overrideDisableZSL);
    pExtend->pTokens[2].id = 2;
    pExtend->pTokens[2].size = sizeof(pStaticSettings->overrideGPURotationUsecase);
    pExtend->pTokens[3].id = 3;
    pExtend->pTokens[3].size = sizeof(pStaticSettings->overrideEnableMFNR);
    pExtend->pTokens[4].id = 4;
    pExtend->pTokens[4].size = sizeof(pStaticSettings->anchorSelectionAlgoForMFNR);
    pExtend->pTokens[5].id = 5;
    pExtend->pTokens[5].size = sizeof(pStaticSettings->overrideHFRNo3AUseCase);
    pExtend->pTokens[6].id = 6;
    pExtend->pTokens[6].size = sizeof(pStaticSettings->overrideForceSensorMode);
    pExtend->pTokens[7].id = 7;
    pExtend->pTokens[7].size = sizeof(pStaticSettings->defaultMaxFPS);
    pExtend->pTokens[8].id = 8;
    pExtend->pTokens[8].size = sizeof(pStaticSettings->fovcEnable);
    pExtend->pTokens[9].id = 9;
    pExtend->pTokens[9].size = sizeof(pStaticSettings->overrideCameraClose);
    pExtend->pTokens[10].id = 10;
    pExtend->pTokens[10].size = sizeof(pStaticSettings->overrideCameraOpen);
    pExtend->pTokens[14].id = 14;
    pExtend->pTokens[14].size = sizeof(pStaticSettings->statsProcessingSkipFactor);
    pExtend->pTokens[16].id = 16;
    pExtend->pTokens[16].size = sizeof(pStaticSettings->dumpDebugDataEveryProcessResult);
    pExtend->pTokens[17].id = 17;
    pExtend->pTokens[17].size = sizeof(pStaticSettings->multiCameraVREnable);
    pExtend->pTokens[18].id = 18;
    pExtend->pTokens[18].size = sizeof(pStaticSettings->overrideGPUDownscaleUsecase);
    pExtend->pTokens[20].id = 20;
    pExtend->pTokens[20].size = sizeof(pStaticSettings->disableASDStatsProcessing);
    pExtend->pTokens[21].id = 21;
    pExtend->pTokens[21].size = sizeof(pStaticSettings->multiCameraFrameSync);
    pExtend->pTokens[22].id = 22;
    pExtend->pTokens[22].size = sizeof(pStaticSettings->outputFormat);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GenerateModifySettingsData
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void GenerateModifySettingsData(
    ChiOverrideModifySetting *pSettings)
{
    const StaticSettings *pStaticSettings = HwEnvironment::GetInstance()->GetStaticSettings();

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[0].pData = const_cast<UINT *>(&(pStaticSettings->overrideForceUsecaseId));
    pSettings[0].token.id = 0;
    pSettings[0].token.size = sizeof(pStaticSettings->overrideForceUsecaseId);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[1].pData = const_cast<UINT *>(&(pStaticSettings->overrideDisableZSL));
    pSettings[1].token.id = 1;
    pSettings[1].token.size = sizeof(pStaticSettings->overrideDisableZSL);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[2].pData = const_cast<UINT *>(&(pStaticSettings->overrideGPURotationUsecase));
    pSettings[2].token.id = 2;
    pSettings[2].token.size = sizeof(pStaticSettings->overrideGPURotationUsecase);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[3].pData = const_cast<UINT *>(&(pStaticSettings->overrideEnableMFNR));
    pSettings[3].token.id = 3;
    pSettings[3].token.size = sizeof(pStaticSettings->overrideEnableMFNR);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[4].pData = const_cast<UINT *>(&(pStaticSettings->anchorSelectionAlgoForMFNR));
    pSettings[4].token.id = 4;
    pSettings[4].token.size = sizeof(pStaticSettings->anchorSelectionAlgoForMFNR);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[5].pData = const_cast<UINT *>(&(pStaticSettings->overrideHFRNo3AUseCase));
    pSettings[5].token.id = 5;
    pSettings[5].token.size = sizeof(pStaticSettings->overrideHFRNo3AUseCase);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[6].pData = const_cast<UINT *>(&(pStaticSettings->overrideForceSensorMode));
    pSettings[6].token.id = 6;
    pSettings[6].token.size = sizeof(pStaticSettings->overrideForceSensorMode);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[7].pData = const_cast<UINT *>(&(pStaticSettings->defaultMaxFPS));
    pSettings[7].token.id = 7;
    pSettings[7].token.size = sizeof(pStaticSettings->defaultMaxFPS);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[8].pData = const_cast<UINT *>(&(pStaticSettings->fovcEnable));
    pSettings[8].token.id = 8;
    pSettings[8].token.size = sizeof(pStaticSettings->fovcEnable);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[9].pData = const_cast<UINT *>(&(pStaticSettings->overrideCameraClose));
    pSettings[9].token.id = 9;
    pSettings[9].token.size = sizeof(pStaticSettings->overrideCameraClose);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[10].pData = const_cast<UINT *>(&(pStaticSettings->overrideCameraOpen));
    pSettings[10].token.id = 10;
    pSettings[10].token.size = sizeof(pStaticSettings->overrideCameraOpen);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[11].pData = const_cast<UINT *>(&(pStaticSettings->EISV2Enable));
    pSettings[11].token.id = 11;
    pSettings[11].token.size = sizeof(pStaticSettings->EISV2Enable);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[12].pData = const_cast<UINT *>(&(pStaticSettings->EISV3Enable));
    pSettings[12].token.id = 12;
    pSettings[12].token.size = sizeof(pStaticSettings->EISV3Enable);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[13].pData = const_cast<UINT *>(&(pStaticSettings->numPCRsBeforeStreamOn));
    pSettings[13].token.id = 13;
    pSettings[13].token.size = sizeof(pStaticSettings->numPCRsBeforeStreamOn);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[14].pData = const_cast<UINT *>(&(pStaticSettings->statsProcessingSkipFactor));
    pSettings[14].token.id = 14;
    pSettings[14].token.size = sizeof(pStaticSettings->statsProcessingSkipFactor);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[15].pData = const_cast<UINT *>(&(pStaticSettings->multiCameraSATEnable));
    pSettings[15].token.id = 15;
    pSettings[15].token.size = sizeof(pStaticSettings->multiCameraSATEnable);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[16].pData = const_cast<UINT *>(&(pStaticSettings->dumpDebugDataEveryProcessResult));
    pSettings[16].token.id = 16;
    pSettings[16].token.size = sizeof(pStaticSettings->dumpDebugDataEveryProcessResult);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[17].pData = const_cast<UINT *>(&(pStaticSettings->multiCameraVREnable));
    pSettings[17].token.id = 17;
    pSettings[17].token.size = sizeof(pStaticSettings->multiCameraVREnable);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[18].pData = const_cast<UINT *>(&(pStaticSettings->overrideGPUDownscaleUsecase));
    pSettings[18].token.id = 18;
    pSettings[18].token.size = sizeof(pStaticSettings->overrideGPUDownscaleUsecase);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[19].pData = const_cast<UINT *>(&(pStaticSettings->advanceFeatureMask));
    pSettings[19].token.id = 19;
    pSettings[19].token.size = sizeof(pStaticSettings->advanceFeatureMask);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[20].pData = const_cast<UINT *>(&(pStaticSettings->disableASDStatsProcessing));
    pSettings[20].token.id = 20;
    pSettings[20].token.size = sizeof(pStaticSettings->disableASDStatsProcessing);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[21].pData = const_cast<UINT *>(&(pStaticSettings->multiCameraFrameSync));
    pSettings[21].token.id = 21;
    pSettings[21].token.size = sizeof(pStaticSettings->multiCameraFrameSync);

    // NOWHINE CP036a: Sample code needs access across typeless interface
    pSettings[22].pData = const_cast<OutputFormatType *>(&(pStaticSettings->outputFormat));
    pSettings[22].token.id = 22;
    pSettings[22].token.size = sizeof(pStaticSettings->outputFormat);

    /// @note id 0xFFFF taken for overrideLogLevels passed only during open
}

CAMX_NAMESPACE_END
